package com.mentalhealthplatform.global.rbac.jwt;

import com.mentalhealthplatform.global.rbac.model.CustomUserDetails;
import com.mentalhealthplatform.global.rbac.model.Endpoint;
import com.mentalhealthplatform.global.rbac.repository.EndpointRepository;
import com.mentalhealthplatform.global.rbac.security.CustomSecurityContext;
import com.mentalhealthplatform.global.rbac.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Optional;

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(JwtRequestFilter.class);

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Autowired
    private EndpointRepository endpointRepository;



    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        String upgradeHeader = request.getHeader("Upgrade");

        // 如果是 WebSocket 握手请求，跳过 JWT 验证
        if (upgradeHeader != null && "websocket".equalsIgnoreCase(upgradeHeader)) {
            logger.info("Skipping JWT filter for WebSocket handshake");
            filterChain.doFilter(request, response);
            return;
        }

        String requestPath = request.getServletPath();
        String requestMethod = request.getMethod();
        logger.info("Incoming request: {} {}", requestMethod, requestPath);

        // 自定义端口请求处理逻辑
        Optional<Endpoint> endpointOpt = endpointRepository.findByPathAndMethod(requestPath, requestMethod);

        if (endpointOpt.isPresent()) {
            Endpoint endpoint = endpointOpt.get();
            logger.info("Found endpoint: {}", endpoint);

            // 存储 Endpoint 信息到安全上下文中
            CustomSecurityContext customSecurityContext = new CustomSecurityContext(endpoint);
            request.setAttribute("customSecurityContext", customSecurityContext);

            // 检查是否允许匿名访问
            if (endpoint.isAllowAnonymous()) {
                logger.info("Endpoint allows anonymous access, skipping JWT validation");
                filterChain.doFilter(request, response);
                return;
            }
        }


        // 身份认证逻辑

        // 提取 JWT 令牌
        final String authorizationHeader = request.getHeader("Authorization");
        String username = null;
        String jwt = null;

        // 如果 Authorization 头部不存在或格式不正确，返回 401
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            logger.warn("No Authorization header or header does not start with Bearer");
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "请求发起错误，未提供有效的凭证。");
            return;
        }

        jwt = authorizationHeader.substring(7);
        logger.info("Authorization header found, JWT extracted");

        try {
            username = jwtUtils.extractUsername(jwt);
            logger.info("Username extracted from JWT: {}", username);
        } catch (Exception e) {
            logger.error("Error extracting username from JWT", e);
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JWT 令牌无效。");
            return;
        }

        // 如果 SecurityContext 没有认证，并且用户名不为空，则进行 JWT 验证
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            logger.info("Username not null and SecurityContext has no authentication, proceeding with token validation");

            // 检查用户是否存在
            CustomUserDetails userDetails;
            try {
                userDetails = userDetailsService.loadUserByUsername(username);
            } catch (Exception e) {
                logger.error("User not found: {}", username);
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "用户不存在或凭证无效。");
                return;
            }

            // 验证 JWT 令牌
            if (jwtUtils.validateToken(jwt, userDetails)) {
                logger.info("JWT token is valid for user: {}", username);

                // 创建并设置 UsernamePasswordAuthenticationToken
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            } else {
                logger.warn("Invalid JWT token for user: {}", username);
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "您的会话已过期或无效，请重新登录。");
                return;
            }
        }

        // 继续过滤器链
        filterChain.doFilter(request, response);
    }

}
